/** * Copyright 2017 Gunnar Morling (http://www.gunnarmorling.de/) * and/or other contributors as indicated by the @authors tag. See the * copyright.txt file in the distribution for a full listing of all * contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.moditect.mavenplugin.generate; import java.io.File; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.shared.artifact.resolve.ArtifactResolver; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.collection.CollectRequest; import org.eclipse.aether.collection.CollectResult; import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.resolution.ArtifactRequest; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.util.graph.selector.AndDependencySelector; import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector; import org.eclipse.aether.util.graph.selector.OptionalDependencySelector; import org.eclipse.aether.util.graph.selector.ScopeDependencySelector; import org.moditect.commands.GenerateModuleInfo; import org.moditect.mavenplugin.common.model.ArtifactConfiguration; import org.moditect.mavenplugin.generate.model.ModuleConfiguration; import org.moditect.mavenplugin.util.MojoLog; import org.moditect.model.DependencyDescriptor; /** * @author Gunnar Morling */ @Mojo(name = "generate-module-info", defaultPhase = LifecyclePhase.GENERATE_SOURCES) public class GenerateModuleInfoMojo extends AbstractMojo { @Component private ArtifactResolver artifactResolver; @Component private ArtifactHandlerManager artifactHandlerManager; @Parameter( defaultValue = "${session}", readonly = true, required = true ) private MavenSession session; @Component private RepositorySystem repoSystem; @Parameter( defaultValue = "${repositorySystemSession}", readonly = true, required = true ) private RepositorySystemSession repoSession; @Parameter( defaultValue = "${project.remoteProjectRepositories}", readonly = true, required = true ) private List<RemoteRepository> remoteRepos; @Parameter(readonly = true, defaultValue = "${project.build.directory}/moditect") private File workingDirectory; @Parameter(property = "outputDirectory", defaultValue = "${project.build.directory}/generated-sources/modules") private File outputDirectory; @Parameter private List<ModuleConfiguration> modules; @Parameter(property = "moditect.artifact") private String artifactOverride; @Parameter(property = "moditect.additionalDependencies") private String additionalDependenciesOverride; @Parameter(property = "moditect.moduleName") private String moduleNameOverride; @Parameter(property = "moditect.exportExcludes") private String exportExcludesOverride; @Parameter(property = "moditect.addServiceUses", defaultValue = "false") private boolean addServiceUsesOverride; @Override public void execute() throws MojoExecutionException, MojoFailureException { createDirectories(); if ( artifactOverride != null ) { processModule( getModuleConfigurationFromOverrides() ); } else { for ( ModuleConfiguration moduleConfiguration : modules ) { processModule( moduleConfiguration ); } } } private ModuleConfiguration getModuleConfigurationFromOverrides() { ModuleConfiguration moduleConfiguration = new ModuleConfiguration(); moduleConfiguration.setArtifact( new ArtifactConfiguration( artifactOverride ) ); moduleConfiguration.setModuleName( moduleNameOverride ); if ( additionalDependenciesOverride != null ) { for ( String additionalDependency : additionalDependenciesOverride.split( "\\," ) ) { moduleConfiguration.getAdditionalDependencies().add( new ArtifactConfiguration( additionalDependency ) ); } } if ( exportExcludesOverride != null ) { moduleConfiguration.getExportExcludes().add( exportExcludesOverride ); } moduleConfiguration.setAddServiceUses( addServiceUsesOverride ); return moduleConfiguration; } private void processModule(ModuleConfiguration moduleConfiguration) throws MojoExecutionException { Artifact inputArtifact = resolveArtifact( new DefaultArtifact( moduleConfiguration.getArtifact().toDependencyString() ) ); Set<DependencyDescriptor> dependencies = getDependencies( inputArtifact ); for( ArtifactConfiguration further : moduleConfiguration.getAdditionalDependencies() ) { Artifact furtherArtifact = resolveArtifact( new DefaultArtifact( further.toDependencyString() ) ); dependencies.add( new DependencyDescriptor( furtherArtifact.getFile().toPath(), false ) ); } new GenerateModuleInfo( inputArtifact.getFile().toPath(), moduleConfiguration.getModuleName(), dependencies, moduleConfiguration.getExportExcludes() .stream() .map( e -> Pattern.compile( e ) ) .collect( Collectors.toList() ), workingDirectory.toPath(), outputDirectory.toPath(), moduleConfiguration.isAddServiceUses(), new MojoLog( getLog() ) ) .run(); } private Set<DependencyDescriptor> getDependencies(Artifact inputArtifact) throws MojoExecutionException { CollectRequest collectRequest = new CollectRequest( new Dependency( inputArtifact, "provided" ), remoteRepos ); CollectResult collectResult = null; try { RepositorySystemSession sessionWithProvided = new DefaultRepositorySystemSession( repoSession ) .setDependencySelector( new AndDependencySelector( new ScopeDependencySelector( "test" ), new OptionalDependencySelector(), new ExclusionDependencySelector() ) ); collectResult = repoSystem.collectDependencies( sessionWithProvided, collectRequest ); } catch (DependencyCollectionException e) { throw new MojoExecutionException( "Couldn't collect dependencies", e ); } Set<DependencyDescriptor> dependencies = new LinkedHashSet<>(); for ( DependencyNode dependency : collectResult.getRoot().getChildren() ) { Artifact resolvedDependency = resolveArtifact( dependency.getDependency().getArtifact() ); dependencies.add( new DependencyDescriptor( resolvedDependency.getFile().toPath(), dependency.getDependency().isOptional() ) ); } return dependencies; } private void createDirectories() { if ( !workingDirectory.exists() ) { workingDirectory.mkdirs(); } if ( !outputDirectory.exists() ) { outputDirectory.mkdirs(); } } private Artifact resolveArtifact(Artifact inputArtifact) throws MojoExecutionException { ArtifactRequest request = new ArtifactRequest(); request.setArtifact( inputArtifact ); request.setRepositories( remoteRepos ); try { return repoSystem.resolveArtifact( repoSession, request ).getArtifact(); } catch (ArtifactResolutionException e) { throw new MojoExecutionException( e.getMessage(), e ); } } }